///作业调度与进程调度模拟实现
#include <stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include<iostream>
#include<list>
#include<queue>
using namespace std;
#define ReadyLimit 2

typedef struct job {   ///模拟JCB/PCB的结构体
    int id;            ///作业/进程标识符
    int needtime;      ///要求运行时间
    int arrivetime;    ///到达时间
    int starttime;     ///开始时间
    int finishtime;    ///结束时间
    int remainder;     ///剩余时间
    double priority;    ///优先权
} jobnode,*jobnodeptr;

list<jobnode> joblist,     ///作业队列
           readylist,   ///就绪队列
           collectlist; ///收集队列

jobnodeptr runlist = nullptr;//运行队列只是一个指针！

int systime;  ///模拟系统时钟


void show(list<jobnode> list)
{
    for(auto& p:list)
        printf("%-7d  %-7d  %-7d  %-7d  %-7d\n", p.id,
               p.needtime, p.arrivetime, p.starttime, p.finishtime);
}



void init(void) ///初始化
{
    systime=0;
}

void file2joblist(void)///从文件读入输入数据
{
    FILE *fp;
    jobnode p,q;
    int i,j;

    fp=fopen("input.txt","rt");
    if (!fp) {
        printf("Can't open file");
        exit(1);
    }
    fscanf(fp,"%d",&i);
    for (j=0; j<i; j++) {
        fscanf(fp,"%d%d%d",&q.id,&q.needtime,&q.arrivetime);
        q.starttime=0;
        q.finishtime=0;
        q.remainder=q.needtime;
        q.priority=-1.0;

        joblist.push_back(q);
    }
    fclose(fp);
}

void jobdispatch(void)///作业调度
{
    /// 要求使用 最高响应比优先调度算法
    double priority_max = -1.0;
    list<jobnode>::iterator iter;
    list<jobnode>::iterator it = joblist.begin();
    int count = 0;//防止进入死循环
    bool yes_no = false;

    while(!joblist.empty() && readylist.size() < ReadyLimit && count < ReadyLimit)//直到插入满就绪队列！
    {
        priority_max = -1.0;
        yes_no = false;
        for (auto it = joblist.begin(); it != joblist.end();)
        {
            int wait_time = systime - it->arrivetime;
            double priority = (it->needtime + wait_time) / it->needtime;
            it->priority = priority;
            if (it->arrivetime <= systime && priority_max < it->priority)//找到本次中的优先级最高的！且到达时间要小于系统时间！
            {
                priority_max = priority;
                iter = it;
                yes_no = true;
            }
            ++it;
        }
        if(yes_no)
        {
            readylist.push_back(*iter); // 插入就绪队列中
            joblist.erase(iter);        // 从后备队列中删除！
        }
        count++;
    }
}

void processdispatch(void)///进程调度
{
    if(!readylist.empty())//就绪队列要不为空！
    {
        runlist = &readylist.front(); // 取出就绪队列里面的第一个任务！
    }
}

void running(void)///模拟运行1个时间片
{
    if(runlist)
    {
        ///   1. remainder（剩余时间）减1，代表模拟运行1个时间片
        runlist->remainder--;
        if (runlist->starttime == 0)
        {
            runlist->starttime = systime; // 开始时间
        }
        ///   2. 若remainder==0，进程运行完毕，节点插入collectlist（收集队列）
        ///   3. 若remainder>0,进程未运行完，节点插入readylist（就绪队列）尾部
        if (runlist->remainder == 0)
        {
            runlist->finishtime = systime;      // 结束时间
            collectlist.push_back(*runlist);    // 插入收集队列
            readylist.erase(readylist.begin()); // 从就绪队列中取出
        }
        else
        {
            readylist.push_back(readylist.front()); // 将未完成的且已经过来时间的片进程插入到尾部
            readylist.erase(readylist.begin());     // 将未完成且已经过了时间片的进程从头部删除
        }
    }
}





void display(void)///显示信息
{
    printf("id-----  need---  arrive-  start--  finish-\n");
    for(auto p: collectlist)
    {
        printf("%-7d  %-7d  %-7d  %-7d  %-7d\n",p.id,\
               p.needtime,p.arrivetime,p.starttime,p.finishtime);
    }
}


int main(void)
{
    init();
    file2joblist();
    // show(joblist);
    // cout << "加载文件成功！" <<endl;

    while(1)
    {
        systime++;
        jobdispatch();
        // show(readylist);
        // sleep(1);
        processdispatch();
        // show(readylist);
        // sleep(1);
        running(); 
        if (joblist.empty() && readylist.empty())
            break;

    }

    printf("\n\n");
    display();
    return 0;
}

